package scene

import (
	"sync"
)

// NewScene 创建新场景实例
// 场景实例负责初始化和管理层，所有AOI相关操作都委托给Layer
func NewScene(id int32, width, height, gridSize float64, enableAOI bool) *Scene {
	// 初始化场景实例
	scene := &Scene{
		width:      width,
		height:     height,
		gridSize:   gridSize,
		enableAOI:  enableAOI,
		maxPlayers: 0,
		id:         id,
		layers:     make([]*Layer, 0),
	}
	return scene
}

// Scene 游戏场景，负责调度和管理所有层
// 场景实例由SceneManager创建和管理，作为Layer的调度者，所有AOI相关操作都委托给Layer
type Scene struct {
	// AOI配置属性
	id         int32   // 场景实例唯一ID
	width      float64 // 宽度
	height     float64 // 高度
	gridSize   float64 // 网格大小
	enableAOI  bool    // AOI开关状态
	maxPlayers int     // 最大玩家数量限制

	// 层管理相关字段
	layers     []*Layer     // 存储所有层的数组
	layerLock  sync.RWMutex // 层锁（用于保护layers切片的并发访问）
	layerIndex int64        // 层索引，用于生成新的层ID
}

// GetID 获取场景ID
func (s *Scene) GetID() int32 {
	return s.id
}

// Width 返回场景宽度
func (s *Scene) Width() float64 {
	return s.width
}

// Height 返回场景高度
func (s *Scene) Height() float64 {
	return s.height
}

// GetGridSize 获取网格大小
func (s *Scene) GetGridSize() float64 {
	return s.gridSize
}

// GetMaxPlayers 获取最大玩家数量
func (s *Scene) GetMaxPlayers() int {
	return s.maxPlayers
}

// SetMaxPlayers 设置最大玩家数量
func (s *Scene) SetMaxPlayers(maxPlayers int) {
	s.maxPlayers = maxPlayers
}

// Load 获取或者创建新层
// 仅仅在添加Player时调用,获得(创建)一个人数未满的层
// 人数上限仅用来在一定范围内控制人数保证性能，实际玩家数量可能会超过maxPlayers
func (s *Scene) load() *Layer {
	for _, layer := range s.layers {
		if layer.CanAddPlayer() {
			return layer
		}
	}
	return s.Create()
}

// Delete 删除指定ID的层
// 注意：删除层会导致该层上的所有实体被移除
func (s *Scene) Delete(layerID int64) bool {
	// 查找层的索引
	index := -1
	for i, layer := range s.layers {
		if layer.GetID() == layerID {
			index = i
			break
		}
	}
	// 检查层是否存在
	if index == -1 {
		return false
	}
	s.layerLock.Lock()
	defer s.layerLock.Unlock()
	// 创建新数组，不包含要删除的层
	newLayers := make([]*Layer, 0, len(s.layers)-1)
	newLayers = append(newLayers, s.layers[:index]...)
	newLayers = append(newLayers, s.layers[index+1:]...)
	s.layers = newLayers

	return true
}

// Join 玩家进入场景，必须死player类型
// 场景负责调度Layer，所有AOI相关操作都委托给Layer
func (s *Scene) Join(entity Entity, x, y float64) bool {
	if entity.GetType() != EntityTypePlayer {
		return false
	}
	layer := s.load()
	if layer == nil {
		return false
	}
	return layer.Add(entity, x, y)
}

// Add 添加实体到指定层
func (s *Scene) Add(p Entity, i int, x, y float64) bool {
	layer := s.layers[i]
	if layer == nil {
		return false
	}
	return layer.Add(p, x, y)
}

// Create 创建副本，一般情况下，只有副本类型才需要创建
func (s *Scene) Create() *Layer {
	s.layerLock.Lock()
	defer s.layerLock.Unlock()
	s.layerIndex++
	layer := NewLayer(s.layerIndex, s)
	s.layers = append(s.layers, layer)
	return layer
}

// Update 更新场景的AOI信息
// 场景负责调度所有层的AOI更新
// 注意：根据业务实际情况，此方法仅遍历已存在的层，无需使用锁保护
func (s *Scene) Update() {
	// 遍历所有层并调用它们的UpdateAOI方法
	for _, layer := range s.layers {
		layer.Update()
	}
}
